﻿#include "Shared.h"

RelocPtr<PlayerCharacter*> g_player(0x0);

bool ReadMemory(uintptr_t addr, void* data, size_t len) {
    unsigned long oldProtect;
    if (VirtualProtect((void *)addr, len, PAGE_EXECUTE_READWRITE, &oldProtect)) {
        memcpy(data, (void*)addr, len);
        if (VirtualProtect((void *)addr, len, oldProtect, &oldProtect))
            return true;
    }
    return false;
}

void DumpClass(void * theClassPtr, u64 nIntsToDump)
{
    u64* basePtr = (u64*)theClassPtr;

    _MESSAGE("DumpClass: %016I64X", basePtr);


    if (!theClassPtr) return;
    for (u64 ix = 0; ix < nIntsToDump; ix++ ) {
        u64* curPtr = basePtr+ix;
        const char* curPtrName = NULL;
        u64 otherPtr = 0;
        float otherFloat1 = 0.0;
        float otherFloat2 = 0.0;
        const char* otherPtrName = NULL;
        if (curPtr) {
            curPtrName = getObjectClassName((void*)curPtr);

            __try
            {
                otherPtr = *curPtr;
                u32 lowerFloat = otherPtr & 0xFFFFFFFF;
                u32 upperFloat = (otherPtr >> 32) & 0xFFFFFFFF;
                otherFloat1 = *(float*)&lowerFloat;
                otherFloat2 = *(float*)&upperFloat;
            }
            __except(EXCEPTION_EXECUTE_HANDLER)
            {
                //
            }

            if (otherPtr) {
                otherPtrName = getObjectClassName((void*)otherPtr);
            }
        }

        _MESSAGE("%3d +%03X ptr: 0x%016I64X: %32s *ptr: 0x%016I64x | %f, %f: %32s", ix, ix*8, curPtr, curPtrName, otherPtr, otherFloat2, otherFloat1, otherPtrName);
    }
}


std::string indent="-";
class traceGFxValue_VisitMembers : public Value::ObjectInterface::ObjVisitor
{
public:
    virtual void Visit(const char* member, Value* value) //override
    {
        _MESSAGE("%s member name: \t\t%s",indent.c_str(), member);
        traceGFxValue(value);
    }
};

void traceGFxValueInt(Value* fxv)
{
    _MESSAGE("%s type:     int\t\tvalue: %16i\t\thex: 0x%016I64X",indent.c_str(), fxv->GetInt(), fxv->GetInt());
}

void traceGFxValueUInt(Value* fxv)
{
    _MESSAGE("%s type:     uint\t\tvalue: %16u\t\thex: 0x%016I64X",indent.c_str(), fxv->GetUInt(), fxv->GetUInt());
}

void traceGFxValueFloat(Value* fxv)
{
    _MESSAGE("%s type:   float\t\tvalue: %16f\t\thex: 0x%016I64X",indent.c_str(), fxv->GetNumber(), fxv->GetNumber());
};

void traceGFxValueBool(Value* fxv)
{
    _MESSAGE("%s type:    bool\t\tvalue: %16s",indent.c_str(), fxv->GetBool() ? "true" : "false");
};

void traceGFxValueString(Value* fxv)
{
    _MESSAGE("%s type:  string\t\tvalue: %16s",indent.c_str(), fxv->GetString());
};

void traceGFxValueArray(Value* fxv)
{
    _MESSAGE("%s type:  array",indent.c_str());
    _MESSAGE("%s type:  array\t\titem count:%i",indent.c_str(), fxv->GetArraySize());


    for (u32 i = 0; i < fxv->GetArraySize(); i++)
    {
        Value item;
        fxv->GetElement(i, &item);
        traceGFxValue(&item);
    };

}

void traceGFxValueObject(Value* fxv)
{
    _MESSAGE("%s type:  object",indent.c_str());
    indent+="-";
    traceGFxValue_VisitMembers dm;
    fxv->VisitMembers(&dm);
    indent.erase(indent.size()-1);

}

void traceGFxValue(Value* fxv)
{
    int type = fxv->Type & 0x8F;

    switch (type)
    {
    case Value::VT_Undefined:
        _MESSAGE("%s type:  kType_Undefined",indent.c_str());
        break;
    case Value::VT_Null:
        _MESSAGE("%s type:  kType_Null",indent.c_str());
        break;
    case Value::VT_Boolean:
        traceGFxValueBool(fxv);
        break;
    case Value::VT_Int:
        traceGFxValueInt(fxv);
        break;
    case Value::VT_UInt:
        traceGFxValueUInt(fxv);
        break;
    case Value::VT_Number:
        traceGFxValueFloat(fxv);
        break;
    case Value::VT_String:
        traceGFxValueString(fxv);
        break;
    case Value::VT_StringW:
        _MESSAGE("%s type:  kType_Unknown7",indent.c_str());
        break;
    case Value::VT_Object:
        traceGFxValueObject(fxv);
        break;
    case Value::VT_Array:
        traceGFxValueArray(fxv);
        break;
    case Value::VT_DisplayObject:
        traceGFxValueObject(fxv);
        break;
    case Value::VT_Function:
        _MESSAGE("%s type:  kType_Function",indent.c_str());
        break;
    default:
        break;
    }
};
